import HybridAppModule from '@expensify/react-native-hybrid-app';
import Onyx from 'react-native-onyx';
import type {OnyxEntry} from 'react-native-onyx';
import CONFIG from '@src/CONFIG';
import CONST from '@src/CONST';
import ONYXKEYS from '@src/ONYXKEYS';
import type {Credentials, HybridApp, Session, TryNewDot} from '@src/types/onyx';
import {isEmptyObject} from '@src/types/utils/EmptyObject';
import {closeReactNativeApp, setReadyToShowAuthScreens, setUseNewDotSignInPage} from './actions/HybridApp';
import Log from './Log';
import {getCurrentUserEmail} from './Network/NetworkStore';

function isAnonymousUser(sessionParam: OnyxEntry<Session>): boolean {
    return sessionParam?.authTokenType === CONST.AUTH_TOKEN_TYPES.ANONYMOUS;
}

let currentHybridApp: OnyxEntry<HybridApp>;
let currentTryNewDot: OnyxEntry<TryNewDot>;
let currentCredentials: OnyxEntry<Credentials>;
let currentSession: OnyxEntry<Session>;

Onyx.connectWithoutView({
    key: ONYXKEYS.HYBRID_APP,
    callback: (hybridApp) => {
        currentHybridApp = hybridApp;
        signInToOldDotAndChooseExperience(hybridApp, currentTryNewDot, currentCredentials, currentSession);
    },
});

Onyx.connectWithoutView({
    key: ONYXKEYS.NVP_TRY_NEW_DOT,
    callback: (tryNewDot) => {
        currentTryNewDot = tryNewDot;
        signInToOldDotAndChooseExperience(currentHybridApp, tryNewDot, currentCredentials, currentSession);
    },
});

Onyx.connectWithoutView({
    key: ONYXKEYS.CREDENTIALS,
    callback: (credentials) => {
        currentCredentials = credentials;
        signInToOldDotAndChooseExperience(currentHybridApp, currentTryNewDot, credentials, currentSession);
    },
});

Onyx.connectWithoutView({
    key: ONYXKEYS.SESSION,
    callback: (session: OnyxEntry<Session>) => {
        currentSession = session;
        signInToOldDotAndChooseExperience(currentHybridApp, currentTryNewDot, currentCredentials, session);
    },
});

let activePolicyID: OnyxEntry<string>;
Onyx.connectWithoutView({
    key: ONYXKEYS.NVP_ACTIVE_POLICY_ID,
    callback: (newActivePolicyID) => {
        activePolicyID = newActivePolicyID;
    },
});

function shouldUseOldApp(tryNewDot: TryNewDot) {
    if (isEmptyObject(tryNewDot) || isEmptyObject(tryNewDot.classicRedirect)) {
        return true;
    }
    return tryNewDot.classicRedirect.dismissed;
}

/**
 * Signs the user into OldDot when session and credentials are available,
 * then decides whether to stay in NewDot or switch to OldDot based on `nvp_tryNewDot`.
 */
function signInToOldDotAndChooseExperience(hybridApp: OnyxEntry<HybridApp>, tryNewDot: OnyxEntry<TryNewDot>, credentials: OnyxEntry<Credentials>, session: OnyxEntry<Session>) {
    if (!CONFIG.IS_HYBRID_APP) {
        return;
    }

    if (!session?.authToken || !hybridApp?.useNewDotSignInPage) {
        return;
    }

    if (isAnonymousUser(session)) {
        setReadyToShowAuthScreens(true);
        return;
    }

    if (!credentials?.autoGeneratedLogin || !credentials?.autoGeneratedPassword) {
        return;
    }

    // Skip if we're already in the signing in flow, preventing multiple calls to signInToOldDot
    if (session?.autoAuthState === CONST.AUTO_AUTH_STATE.SIGNING_IN) {
        return;
    }

    Log.info(`[HybridApp] Performing sign-in on OldDot side`);
    HybridAppModule.signInToOldDot({
        autoGeneratedLogin: credentials.autoGeneratedLogin,
        autoGeneratedPassword: credentials.autoGeneratedPassword,
        authToken: session.authToken,
        email: getCurrentUserEmail() ?? '',
        // eslint-disable-next-line rulesdir/no-default-id-values
        policyID: activePolicyID ?? '',
        signingInWithSAML: hybridApp?.signingInWithSAML ?? false,
    });

    if (tryNewDot !== undefined) {
        setUseNewDotSignInPage(false).then(() => {
            if (shouldUseOldApp(tryNewDot)) {
                closeReactNativeApp({shouldSetNVP: false});
            } else {
                setReadyToShowAuthScreens(true);
            }
        });
    }
}
